/**
 * @properties={typeid:35,uuid:"ad735864-0c9c-47c5-b535-40aa8124dd44"}
 */
var mod_sql_defaultServerName = '';

/**
 * @properties={typeid:24,uuid:"384e7c47-351d-4f37-b43a-cadd7b0eafce"}
 */
function mod_sql_init()
{
	globals.mod_sql_defaultServerName = arguments[0];
	globals.mod_sql_extend();
}

/**
 * @properties={typeid:24,uuid:"efa720ec-9f9e-4dc2-9140-b8f79d39b966"}
 */
function mod_sql_extend()
{
	// Create namespace
	SQLGen = {
		Version: 0.1
	}
	// Define constants
	SQLGen.SELECT = "SELECT";
	SQLGen.ARGUMENTERROR = "Invalid Arguments";
	SQLGen.JOIN = 'JOIN';
	SQLGen.INNERJOIN = 'INNER JOIN';
	SQLGen.LEFTJOIN = 'LEFT JOIN';
	
	// Create query object
	SQLGen.Query = function() {
		this.queryType = SQLGen.SELECT;
		this.pkArray = new Array();
		this.joins = new Array();
		this.joinArgs = new Array();
		this.conditions = new Array();
		this.conditionArgs = new Array();
		this.sorts = new Array();
	}
	SQLGen.Query.prototype.reset = function() {
		this.queryType = SQLGen.SELECT;
		this.pkArray = new Array();
		this.joins = new Array();
		this.joinArgs = new Array();
		this.conditions = new Array();
		this.conditionArgs = new Array();
		this.sorts = new Array();
	}
	
	// 'find' (alias select) method sets up table/server for use in the query
	SQLGen.Query.prototype.find = function(tableName, serverName) {
		this.queryType = SQLGen.SELECT;
		this.serverName = serverName ? serverName : globals.mod_sql_defaultServerName;
		this.tableName = tableName;
		this.table = databaseManager.getTable(this.serverName, this.tableName);
		this.pkArray = this.table.getRowIdentifierColumnNames();
		return this;
	}
	SQLGen.Query.prototype.select = SQLGen.Query.prototype.find; // alias find
	
	// WHERE criteria 
	SQLGen.Query.prototype.where = function(conditions) {
		var flDoNotPrefix = arguments[1] || false;
		switch(typeof conditions)
		{
			case "string" : this.conditions[this.conditions.length] = conditions; break;
			case "object" : 
				if(typeof conditions.length != 'number') throw(SQLGen.ARGUMENTERROR);
				if(!flDoNotPrefix && this.conditions.length > 0)
					conditions[0] = "AND " + conditions[0];
				this.conditions[this.conditions.length] = conditions.shift(); 
				this.conditionArgs = this.conditionArgs.concat(conditions);
				break;
			default : throw(SQLGen.ARGUMENTERROR);
		}
		return this;
	}
	SQLGen.Query.prototype.and = function(conditions) {
		switch(typeof conditions)
		{
			case "string" : conditions = "AND " + conditions; break;
			case "object" : 
				if(typeof conditions.length != 'number') throw(SQLGen.ARGUMENTERROR);
				if(this.conditions.length > 0)
					conditions[0] = "AND " + conditions[0]; break;
		}
		this.where(conditions, true);
		return this;
	}
	SQLGen.Query.prototype.or = function(conditions) {
		switch(typeof conditions)
		{
			case "string" : conditions = "OR " + conditions; break;
			case "object" : 
				if(typeof conditions.length != 'number') throw(SQLGen.ARGUMENTERROR);
				if(this.conditions.length > 0)
					conditions[0] = "OR " + conditions[0]; break;
		}
		this.where(conditions, true);
		return this;
	}
	
	// JOINS
	SQLGen.Query.prototype.joinTemplate = function(joinType, tableName, join) {
		switch(typeof join)
		{
			case "string" : this.joins[this.joins.length] = [joinType, tableName, join]; break;
			case "object" : 
				if(typeof join.length != 'number') throw(SQLGen.ARGUMENTERROR);
				this.joins[this.joins.length] = [joinType, tableName, join.shift()]; 
				this.joinArgs = this.joinArgs.concat(join);
				break;
			default : throw(SQLGen.ARGUMENTERROR);
		}
		return this;
	}
	SQLGen.Query.prototype.join = function(tableName, join) {
		return this.joinTemplate(SQLGen.JOIN, tableName, join);
	}
	SQLGen.Query.prototype.innerjoin = function(tableName, join) {
		return this.joinTemplate(SQLGen.INNERJOIN, tableName, join);
	}
	SQLGen.Query.prototype.leftjoin = function(tableName, join) {
		return this.joinTemplate(SQLGen.LEFTJOIN, tableName, join);
	}
	
	// OUTPUT functions
	SQLGen.Query.prototype.toString = function() {
		switch(this.queryType)
		{
			case SQLGen.SELECT : return this.toSelectString();
			default : throw("Invalid query type");
		}
	}
	SQLGen.Query.prototype.toSelectString = function() {
		var sql = SQLGen.SELECT + " ";
		for(var ix=0; ix<this.pkArray.length; ix++)
		{	
			sql += this.tableName + '.' + this.pkArray[ix];
			if(ix<(this.pkArray.length-1)) sql += ',';
		}
		sql += ' FROM ' + this.tableName + '\n';
		if(this.joins.length > 0)
		{
			for(var ix=0; ix<this.joins.length; ix++)
			{
				sql += this.joins[ix][0] + ' ' + this.joins[ix][1] + " ON " + this.joins[ix][2] + '\n';
			}
		}
		if(this.conditions.length > 0)
		{
			sql += "WHERE " + this.conditions.join(' ') + '\n';
		}
		return sql;
	}
	
	SQLGen.Query.prototype.args = function() {
		return this.joinArgs.concat(this.conditionArgs);
	}
	
	// loader
	SQLGen.Query.prototype.load = function(obj) {
		obj.loadRecords(this.toString(), this.args());
	}

	// setup global reference
	$sql = function() { return new SQLGen.Query(); }
}

/**
 * @properties={typeid:24,uuid:"3a7a84ab-5794-49b2-8811-8b23c5de080f"}
 */
function mod_sql_TEST()
{
	
}
